package com.example.cameraapplication;


import android.Manifest;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.ImageFormat;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.media.Image;
import android.media.ImageReader;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;

import java.nio.ByteBuffer;
import java.util.Arrays;

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public class CameraHelper {

    private static final String TAG = CameraHelper.class.getSimpleName();
    private Activity context;
    private CameraDevice cameraDevice;
    private ImageReader imageReader;
    private SurfaceView surface;
    private SurfaceHolder surfaceHolder;
    private CameraManager cameraManager; //摄像头管理
    private Handler cameraHandler; //后台处理图片传输帧
    private CameraCaptureSession cameraCaptureSession;//控制摄像头预览或拍照
    private HandlerThread handlerThread;

    CameraDevice.StateCallback deviceCallback; //摄像头监听
    CameraCaptureSession.CaptureCallback captureCallback; // 预览拍照监听


    private static final int MAX_PREVIEW_WIDTH = 1920;//Max preview width that is guaranteed by Camera2 API
    private static final int MAX_PREVIEW_HEIGHT = 1080;//Max preview height that is guaranteed by Camera2 API


    public CameraHelper() {

    }

    public CameraHelper(Activity mainActivity, SurfaceView surface) {

        this.surface = surface;
        this.context = mainActivity;

        initData();
    }

    //为摄像头开一个线程
    private void startHandler(){
         handlerThread = new HandlerThread("camera");
        handlerThread.start();
        cameraHandler = new Handler(handlerThread.getLooper());//handler与线程进行绑定
    }

    //关闭线程
    private void destoryHandler(){

        if (handlerThread == null) {
            return;
        }
        handlerThread.quitSafely();
        try {
            handlerThread.join(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


    public void initData() {

        cameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);

        startHandler();

        //imageReader通过将得到的图片存放在队列中，再取出来进行操作
        //队列满了就不再放入新的图片，设置图片队列大小为10
        imageReader = ImageReader.newInstance(MAX_PREVIEW_WIDTH,MAX_PREVIEW_HEIGHT, ImageFormat.JPEG,10);

        imageReader.setOnImageAvailableListener(reader -> {

            //取出最新的图片并清除队列里的旧图片
            Image image = reader.acquireLatestImage();
            //todo 对获取的图片进行操作

            //将图片转换成Bitmap
            ByteBuffer buffer = image.getPlanes()[0].getBuffer();
            byte[] bytes = new byte[buffer.remaining()];
            buffer.get(bytes);//由缓冲区存入字节数组

            final Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);

            //释放资源
            image.close();

        },cameraHandler);//由handler去执行这里面的代码

        deviceCallback = new CameraDevice.StateCallback() {
            @Override
            public void onOpened(@NonNull CameraDevice camera) {

                cameraDevice = camera;
                takePreview();
            }

            @Override
            public void onDisconnected(@NonNull CameraDevice camera) {
                closeCamera();
            }

            @Override
            public void onError(@NonNull CameraDevice camera, int error) {

                closeCamera();
                Toast.makeText(context,"摄像头打开错误",Toast.LENGTH_SHORT).show();
            }
        };

        captureCallback = new CameraCaptureSession.CaptureCallback() {
            @Override
            public void onCaptureStarted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, long timestamp, long frameNumber) {
                super.onCaptureStarted(session, request, timestamp, frameNumber);
            }
        };

        surfaceHolder = surface.getHolder();
        surfaceHolder.addCallback(new SurfaceHolder.Callback() {
            @Override
            public void surfaceCreated(@NonNull SurfaceHolder holder) {
                initCamera();
            }

            @Override
            public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {

            }

            @Override
            public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
                closeCamera();
            }
        });

    }


    //使用后置摄像头
    public void initCamera() {

        String cameraId = "" + CameraCharacteristics.LENS_FACING_FRONT;//得到后摄像头编号

        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            return;
        }


        try {
            cameraManager.openCamera(cameraId, deviceCallback, cameraHandler);
        } catch (CameraAccessException e) {
            Toast.makeText(context,"cameraManager访问摄像头失败",Toast.LENGTH_SHORT).show();
            Log.e(TAG,"cameraManager访问摄像头失败");
        }

    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public String[] getCameras() throws CameraAccessException {
        String[] cameras = new String[0];

        cameras = cameraManager.getCameraIdList();

        return cameras;
    }

    //开启预览
    public void takePreview() {

        try {
            CaptureRequest.Builder previewRequestBuilder = cameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            //将预览数据传递
            previewRequestBuilder.addTarget(imageReader.getSurface());
            previewRequestBuilder.addTarget(surfaceHolder.getSurface());
            // 自动对焦
            previewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            // 打开闪光灯
            previewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);

            cameraDevice.createCaptureSession(Arrays.asList(surfaceHolder.getSurface(), imageReader.getSurface()), new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(@NonNull CameraCaptureSession session) {

                    cameraCaptureSession = session;

                    CaptureRequest captureRequest = previewRequestBuilder.build();
                    try {
                        cameraCaptureSession.setRepeatingRequest(captureRequest,captureCallback,cameraHandler);

                    } catch (CameraAccessException e) {

                        Toast.makeText(context,"cameraCaptureSession访问摄像头失败",Toast.LENGTH_SHORT).show();
                        Log.e(TAG,"cameraCaptureSession访问摄像头失败");
                    }
                }
                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession session) {

                }
            },null);

        } catch (CameraAccessException e) {
            Toast.makeText(context,"CaptureRequest.Builder访问摄像头失败",Toast.LENGTH_SHORT).show();
            Log.e(TAG,"CaptureRequest.Builder访问摄像头失败");
        }
    }

    //关闭摄像头
    public void closeCamera(){
        if (cameraDevice==null) {
            return;
        }
        cameraDevice.close();
        cameraDevice = null;
    }

   public void destory(){
        closeCamera();
        destoryHandler();
    }
}
